home *** CD-ROM | disk | FTP | other *** search
-
- ╒═══════════════════════════════════════════════════════════════╗
- │■ ■ ║
- │ ║
- │ █████████░ ██░ ║
- │ ██░ ██░ ██░ ██░ ██████░ ██░ ████████░ ██░ ██░ ║
- │ ██░ ██░ ██░ ██░ ██░ ██░ ██░ ██░ ██░ ██░ ║
- │ ██░ ██░ ██░ ██░ ██░ ██░ ████████░ ██░ ██░ ║
- │ ██░ ██░ ██░ ██░ ██░ ██░ ██░ ██░ ██░ ██░ ██░ ║
- │ █████████░ ████████░ ██░ ██████░ ██░ ██░ ███░ ███░ ║
- │ ║
- │ T ∙ R ∙ I ∙ A ∙ D ║
- │■ ■ ║
- └───────────────────────────────────────────────────────────────╜
- ╔══════════════╗
- ║ ∙ PRESENTS ∙ ║
- ╚══════════════╝
-
-
- Chain-4 Documentary Version 2.0
- ───────────────────────────────────────────────────────────────────────────────
- Written By : Vulture Total Files : 2
- File Type : Textfile Release Date : 17th of June 1995
- Difficulty : Medium level Filename : CHAINDOC.ZIP
- ───────────────────────────────────────────────────────────────────────────────
-
- Note: This is version 2.0. It includes some pascal procedures at the end of
- the document.
-
- I started writing this little document as a helpfile for myself coz I think
- a great way to learn is writing things down. I found myself having troubles
- understanding the assembler code found in various trainers so I thought it
- was a good idea to make a textfile wich covered some of the main tricks there
- are concerning chain-4 code. Worked out great! Infact, I think this file can
- be of great help to all starting gfxcoders out there, so I have decided to
- release it into the public domain. There are already lots of docs available
- on the subject but there's always room for one more, eh? :)
- Hmm, I will assume you know a little about VGA programming and assembler code.
- If you don't know anything about it yet, this doc might be a little hard to
- understand. If you are already a chain-4 guru, you can go back to sleep coz
- this is probably too easy for you. This document describes the very basics of
- chain-4. But anyway, enough of thiz cr*p. . . on with the real stuff :)
-
-
- =-=-=-=-=-=-=-=-=-=-=-=-= CHAIN-4 VIDEOMODE DOCFILE =-=-=-=-=-=-=-=-=-=-=-=-=-
-
- =-= What is chain-4 ? =-=
-
- Most VGA intros are written in mode 13h. This is 320*200*256 mode. The memory
- in this mode is lineair and thus fairly easy to handle. The resolution isn't
- that great but for most intros it's enough. One can make very cewl graphics
- in this mode. So all in all this is a great mode to use. However, a major
- disadvantage is the fact that only 64 kB of VGA memory can be accessed.
- This is the entire screen (320*200 = almost 64kB = 1 page) you see in front
- of you. So, when you use this mode you aren't using the full standard 256kB
- of memory present on the VGA-card but just 64kB. For most people mode 13h is
- sufficient but for the more serious coders it just isn't enough. They want to
- use the full 256 kB of memory available for e.g fast pageflipping, full screen
- scrolling and lots of other cewl things. Here we go:
- Chain-4 is a method of accessing 256 kB of memory on a standard VGA-card.
- When using chain-4 the VGA memory is unchained wich bassicly means that the
- memory is no longer lineair as were the case in standard mode 13h. Due to VGA
- hardware this gives us 256 kB of memory. On a chain-4 screen pixels are placed
- on so-called bitplanes. Normally there are four pages (=planes) available,
- each 64kB big. This is coz a segment can only be 64 kB big. And 4*64kB=256kB.
- It is also possible to 'tweak' the videomode and get into higher resolutions.
- E.g 320*240*256. This results in you having less pages available because
- you have more pixels on a page. However, in this doc I will not go into
- tweaking the videomode but stay with the basics.
- Take a look at the following diagram. It shows a possible chain-4 screen.
-
- 0 X 640
- ┌──────────────────────┐
- │ =>┌────────┐ │
- │ │ View │ │ The viewport always shows 1/4=64k of the
- │ │ Port │ │ total chain-4 screen. In this case the
- │ │ │ │ chain-4 screen is 2 pages width and 2
- Y │ └────────┘ │ pages high. The total chain-4 screen can
- │ │ be anything that adds up to 4 pages.
- │ Chain-4 screen │ More of this l8r downbelow.
- │ │
- └──────────────────────┘
- 400
-
- The memory layout of the chain-4 screen is rather different from the normal
- MCGA gfxmode. Like I said previously, the memory is divided into 4 bitplanes.
- Each 64 kB big because of segmentlimitations. The following picture should
- clear some things. Suppose you are plotting pixels with colors 0 to 9.
- If the color has reached value 9, it's set to 0 again. Take a look:
-
- The standard lineair MCGA mode gives us:
-
- ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
- │00│01│02│03│04│05│06│07│08│09│00│01│...etc...
-
-
- In unchained VGA memory, the screen will be represented as follows:
-
- Plane 0:
-
- Address: 0 10 70 79 (Not 319 anymore)
- ┌──────────────────────────────────────┐
- │0482604826048260 ..... 0482604826│
- │ │
-
- Plane 1:
-
- Address: 0 10 70 79
- ┌──────────────────────────────────────┐
- │1593715937159371 ..... 1593715937│
- │ │
-
- Plane 2:
-
- Address: 0 10 70 79
- ┌──────────────────────────────────────┐
- │2604826048260482 ..... 2604826048│
- │ │
-
- Plane 3:
-
- Address: 0 10 70 79
- ┌──────────────────────────────────────┐
- │3715937159371593 ..... 3715937159│
- │ │
-
- This means that when you point to an address, you are actually pointing to
- the addresses of FOUR neighbouring pixels. To be more exact: address 0
- points to pixels 0,1,2 and 3, each on different planes. Adress 1 points to
- pixels 4,5,6 and 7, etcetera. Now, before writing the pixel, you will have to
- enable the plane of the pixel you want. If pixel P is in plane I, pixel P+1
- will be in plane (I+1)%4. The screenwidth is now set to 80 instead of 320.
- This should make perfect sence. Think about it. One adress points to 4 pixels.
- Multiply 80 by 4 and you'll get your basic 320 again. And there are still 320
- pixels across visible. 200 pixels in height remains the same. Simple!
-
- So, that's a bit different, eh? Also more difficult to code. But don't let it
- scare you. The advantages you gain from using this mode are well worth the
- effort. And besides, you have this doc so it's not that hard anymore :)
-
- This document explains how to access the unchained videomode, enable
- planes for writing and reading, moving across the screens and putting
- pixels on the screens.
-
- A. How to access the unchained VGA mode.
- B. How to activate the plane we want to write to.
- C. How to activate the plane we want to read from.
- D. How to move across the various planes (screens).
- E. How to place a pixel on the chain-4 screen.
- F. Various pascal procedures concerning this code.
- G. Closing words.
-
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
- A. HOW TO ACCESS THE UNCHAINED VGA MODE.
-
- This is done by setting various vga registers. The code below is very
- basic and can be expanded but it's suitable for our needs right now.
-
- 1. Get into MCGA mode.
- Done by a simple bios-call.
-
- mov ax,0013h ; Videomode 13h 320*200*256
- int 10h ; Set the mode
-
- 2. Unchain VGA-mode.
- This is done by turning the 3rd bit in index 4 of the sequencer off.
-
- mov dx,03c4h ; Sequencer Address Register
- mov al,4 ; Index 4 - Memory mode
- out dx,al ; Select it
- inc dx ; 03c5h - Here we set the mem mode.
- in al,dx ; Get settings inside register
- and al,11110111b ; Disable 3rd bit will give us chain-4
- or al,00000100b ; Bit 2 enabled => no odd/even-scheme
- out dx,al ; Inform VGA
-
- 3. Turn off doubleword mode by setting the Underline Location register
- Use CRT controllers port 3d4h index 14h
-
- mov dx,3d4h
- mov al,14h ; Select index 14 "Underline Location Register"
- out dx,al
- inc dx
- in al,dx
- and al,10111111b ; Bit 6 := 0 => Disable double word adressing
- out dx,al
-
- 4. Turn off word adressing by setting the Mode Control register.
- Now use CRT controllers port 3d4h index 17h
-
- mov dx,3d4h
- mov al,17h ; Mode Control Register
- out dx,al
- inc dx
- in al,dx ; Get what's in the register
- or al,01000000b ; Bit 6 := 1
- out dx,al ; Thus disabling wordmode
-
- 5. Set the logical screen width.
- To do this, use the CRT controllers port 3d4h index 13h.
-
- mov dx,3d4h ; Select the port
- mov al,13h ; Select index Logical Screen Width
- out dx,al ; Inform VGA about it
- inc dx ; Increase port value
- mov al,[Size] ; Set the size
- out dx,al ; Give info to VGA
-
- Like I stated previously, the chain-4 screen can be any size that adds
- up to 4 screens with a screen being 320*200 pixels large (=64kB).
- Size * 8 is how many pixels across there are on the chain-4 screen.
- Examine this:
- Size = 40 => 320 pixels across = 1 screen across, 4 screens down
- Size = 80 => 640 pixels across = 2 screens across, 2 screens down
- Size = 160 => 1280 pixels across = 4 screens across, 1 screen down
- These are all possibilities. Remember, only 320 pixels across are visible.
- We need to know the size of the screen for almost all dealings with the
- chain-4 screen so it's clever to put the size in a constant. Just like I did
- in the example code.
-
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
- B. HOW TO ACTIVATE THE PLANE WE WANT TO WRITE TO.
-
- Before we can plot a pixel on the chain-4 screen, we have to select and
- activate the plane we want to write to. You must alter the 4 least signifi-
- cant bits (bits 0,1,2 and/or 3) in index 2 (set/reset enable register) of
- the graphics controller. This is done as follows:
-
- 1. Select gfx controller: port 3ceh
- mov dx,3ceh
- 2. Select index 2 => Set/reset enable register
- mov al,02
- 3. Pass info to VGA
- out dx,al
- 4. Increase port value
- inc dx
- 5. Select plane for writing ; 1 = on 0 = off
- mov al,00000001b ; enables plane 0 (byte=76543210)
- 6. Give info to VGA
- out dx,al
-
- So, to enable plane 0 for writing:
-
- mov dx,3ceh ; Select port
- mov al,02 ; Select index
- out dx,al ; Give info to VGA
- inc dx ; Increase port value (datafield)
- mov al,00000001b ; Enable plane 0 (bit 0 is now set)
- out dx,al ; Inform VGA 'bout thiz
-
- For all other planes the same code can be used. Just change the MOV command.
- You can also use the AND command for this purpose. Play with it and learn.
- All 4 planes can be set for writing to so you can set 4 pixels at the same
- time with just 1 movsb. Simply enable the 4 least significant bits at once.
- Wow! This is fast... :)
-
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
- C. HOW TO ACTIVATE THE PLANE WE WANT TO READ FROM.
-
- Same goes for reading. First activate the plane and then read the pixel.
- Do it like thiz:
-
- 1. Select gfx controller port 3ceh
- mov dx,3ceh
- 2. Select index
- mov al,04 ; Read plane index
- 3. Inform VGA about this
- out dx,al
- 4. Increase port value
- inc dx
- 5. Select plane for reading
- mov al,00000000b ; Select plane 0 for reading
- 6. Inform VGA
- out dx,al
-
- Bits 0 and 1 must be altered to select a plane for reading. (byte=76543210)
- 00: plane 0 read enable.
- 01: plane 1 read enable.
- 10: plane 2 read enable.
- 11: plane 3 read enable.
- As you might have guessed, you cannot read from all planes at the same time.
-
- So, to enable plane 0 for reading, you'd do the following:
-
- mov dx,3ceh ; Select port
- mov al,04 ; Select index
- out dx,al ; Give info to VGA
- inc dx ; Increase port value
- mov al,00000000b ; Enable plane 0 (since all bits are zero)
- out dx,al ; Inform VGA
-
- That's it. Easy enough, eh? :)
-
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
- D. HOW TO MOVE ACROSS THE VARIOUS PLANES (=screens).
-
- We move across the screens by changing the upperleft adress of the viewport.
-
- ┌─────────────────────────────────────┐
- │ =>┌────────┐ │
- │ │ View │ Chain-4 │ The viewport always shows 1/4 of the
- │ │ Port │ Screen │ total Chain-4 screen.
- │ │ │ │
- │ └────────┘ │
- └─────────────────────────────────────┘
-
- This is of course an excellent way to scroll. Having a big picture on two or
- more screens and then moving the viewport over the screens is much faster than
- trying to scroll the screen in plain MCGA mode. Just takes a view port-writes.
- To do this trick, we have to use the Crt controller port 03d4h. We need index
- 0Ch and 0Dh. That's Start Adress High and Start Adress Low.
-
- 1. Select Crt port
- mov dx,03d4h
- 2. Select index 0Ch
- mov al,0Ch ; Start adress High
- 3. Inform VGA
- out dx,al
- 4. Increase port-value
- inc dx ; Data register
- 5. Move high byte into al
- mov al,bh ; Assuming bx contains total adress
- 6. Change VGA settings
- out dx,al
-
- Now we have set the high byte of the total adress. Only thing left to do is
- set the low byte too. This is done the similar way except we use index 0Dh.
-
- 1. Select Crt port
- mov dx,03d4h
- 2. Select index 0Dh
- mov al,0Dh ; Start adress Low
- 3. Inform VGA
- out dx,al
- 4. Increase port-value
- inc dx
- 5. Move low byte into al
- mov al,bl ; Assuming bx contains total adress
- 6. Change VGA settings
- out dx,al
-
- Now we have set the total new adress of the viewport and have moved the
- entire viewport across the entire chain-4 screen. E.g you can go into a loop
- where you let a picture bounce on the bottom of the screen by changing the
- startingadress of the viewport. That would be pretty cewl, eh? :)
-
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
- E. HOW TO PLACE PIXELS ON THE CHAIN-4 SCREEN.
-
- Ofcourse we want to plot pixels on the screen. But since we are dealing with
- various planes, this is not so simple as on a MCGA screen. We have to know
- on wich plane we want to plot the pixel and howfar into the plane we must be.
- To find the plane we wish to plot on, we do this calculation (x mod 4), and
- the x-coordinate on that plane is found by (x div 4). We work out our y by
- multiplying it by the size of our chain-4 screen. This all might sound a bit
- strange. Why not make a small program to see what I mean? Anyway, in steps:
-
- 1. Multiply Y by our screensize (40,80 or 160)
- y*size
- 2. Find out hofar in the plane we must be
- x div 4
- 3. Finalize location
- y:=y+x
- 4. Find out on wich plane to plot
- x mod 4
- 5. Set that plane
- 6. Plot the pixel
-
- And now for the assember code:
-
- mov ax,[Y] ; Put Y in ax
- xor bx,bx ; Reset bx to zero
- mov bl,[Size] ; Size in bl (it's a byte!)
- imul bx ; Now ax:=ax*bx => Y:=Y*Size
- shl ax,1 ; Multiply by 2 => Y:=Y*2 (Dunno why)
- mov bx,ax ; Save Y-value in bx
- mov ax,[X] ; Move X-value into ax
- mov cx,ax ; And in cx
- shr ax,2 ; Divide ax by 4 (x div 4)
- add bx,ax ; Y:=Y+X bx contains final location
- and cx,00000011b ; cl:=0,1,2 or 3 (x mod 4)
- mov ah,00000001b ; Start value = plane 0
- shl ah,cl ; E.g plane 2: 00000001 => 00000100
- mov dx,3c4h ; Sequencer Register
- mov al,2 ; Select index 2 => plane enable
- out dx,ax ; Enable selected plane
- mov ax,0a000h ; VGA segment
- mov es,ax ; es points to VGA
- mov al,[col] ; Color in al
- mov es:[bx], al ; Place it
-
- This is a complete chain-4 putpixel procedure. You can ofcourse make a pascal
- procedure out of it. Look at the next chapter for that one. The procedure can
- ofcourse be optimized but then... what can't :)
-
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
- F. VARIOUS PASCAL PROCEDURES CONVERNING THIS CODE.
-
- I have included some pascal procedures for you to examine/use. The code works
- just fine and you should not have any troubles implementing this in your own
- programs.
-
- Procedure SetChain4; Assembler; { Get into Chain-4 videomode }
- Asm
- mov ax,0013h { Videomode 13h 320*200*256 }
- int 10h { Set the mode }
-
- mov dx,03c4h { Sequencer Address Register }
- mov al,4 { Index 4 - Memory mode }
- out dx,al { Select it }
- inc dx { 03c5h - Here we set the mem mode }
- in al,dx { Get settings inside register }
- and al,11110111b { Disable 3rd bit will give us chain4 }
- or al,00000100b { Bit 2 enabled => no odd/even-scheme }
- out dx,al { Inform VGA }
-
- mov dx,3d4h
- mov al,14h { Turn off Double Word mode }
- out dx,al
- inc dx
- in al,dx
- and al,10111111b { Bit 6 := 0 => Disable double word adressing }
- out dx,al
- mov dx,3d4h
- mov al,17h { Mode Control Register }
- out dx,al
- inc dx
- in al,dx { Get what's in the register }
- or al,01000000b { Bit 6 := 1 => Address memory as lineair array }
- out dx,al
-
- mov dx,3d4h { Select the port }
- mov al,13h { Select the index Logical Screen Width }
- out dx,al { Inform VGA about it }
- inc dx { Increase port value }
- mov al,[Size] { Set the size }
- out dx,al { Give info to VGA }
- End;
-
- Procedure Cls_C4; Assembler;
- Asm
- mov dx,03c4h { Select port 03c4h }
- mov al,2 { Map Mask Register }
- out dx,al
- inc dx
- mov al,00001111b { Select all planes for writing }
- out dx,al { So we can clear all planes at once }
-
- mov ax,0a000h
- mov es,ax
- xor di,di { Set es:di = Screen Mem }
- mov ax,0 { Color to put = black }
- mov cx,32768 { 32768 (words) * 2 = 65536 bytes = 1 screen }
-
- cld
- rep stosw { Clear it }
- End;
-
- Procedure SetPixelC4(X,Y:Integer; Color:Byte); Assembler;
- Asm
- mov ax,[Y] { Put Y in ax }
- xor bx,bx { Reset bx to zero }
- mov bl,[Size] { Size in bl (it's a Byte!) }
- imul bx { Now ax:=ax*bx => Y:=Y*Size }
- shl ax,1 { Multiply by 2 => Y:=Y*2 (Dunno why) }
- mov bx,ax { Save Y-value in bx }
- mov ax,[X] { Move X-value into ax }
- mov cx,ax { And in cx }
- shr ax,2 { Divide ax by 4 (x div 4) }
- add bx,ax { Y:=Y+X bx contains final location }
- and cx,00000011b { cl:=0,1,2 or 3 (x mod 4) }
- mov ah,00000001b { Start value (plane 0) }
- shl ah,cl { Eg plane 2: 00000001 => 00000100 }
- mov dx,3c4h { Sequencer Register }
- mov al,2 { Select index 2 => plane enable }
- out dx,ax { Enable selected plane }
- mov ax,0a000h { VGA segment }
- mov es,ax { es points to VGA }
- mov al,[Color] { Color in al }
- mov es:[bx], al { Place it }
- End;
-
- Procedure MoveTo(X,Y : Integer); Assembler;
- Asm
- mov ax,[Y] { Y value }
- xor bx,bx { Reset bx to zero }
- mov bl,[Size] { Size in bl }
- shl bx,1 { *2 (dunno why) }
- imul bx { Multiply Y with size }
- mov bx,ax { Save Y into BX }
-
- add bx,[X] { Y:=Y+X }
-
- mov dx,03d4h { CRTC address register }
- mov al,0ch { Start Address High register }
- out dx,al
- inc dx
- mov al,bh { Send high byte of start address }
- out dx,al
-
- dec dx
- mov al,0dh { Start Address Low register }
- out dx,al
- inc dx
- mov al,bl { Send low byte of start address }
- out dx,al
- End;
-
- That's it. It should be easy enough to make a small sample-program with these
- procedures. Why don't you try to scroll a fullscreen picture with this...
-
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
- G. CLOSING WORDS
-
- Thanx must go to Denthor & Eze of Aphyxia and Robert Smith for providing info
- on the topic. If you haven't got their documents, I suggest you get them.
- They are quite good and can be found on various FTP-sites and BBSses.
-
- Hmm, well, the following cr*p is supposed to be stated so here we go:
- I (Vulture) take no responsibility for any mistakes found in this document.
- So use at your own risk. I have used this code myself and did not have any
- problems with it so this code should not give ya a hard time.
-
- Wanna contact Outlaw for some reason? Then call one of the Outlaw distros
- and leave a message.
-
- If U actually use this info, a greet to all people stated above would be
- appreciated. A little graditude doesn't hurt, does it? :)
-
- One thing left to say. Be carefull doing this kinda stuff when you are a
- beginner. Just take it one step at the time. (I did)
-
-
-
- Signed: Vulture / Outlaw Triad / Cri
-
-
- ─────────────────────────┬───────────────────────┬────────────────────────────
- Outlaw Triad Distros : │ Greetz from Outlaw: │ Releases sofar:
- ─────────────────────────┼───────────────────────┼────────────────────────────
- │ │
- ■ Blue Thunder ■ │ - DemoLisher │ ■ MESSAGE (dosscroller)
- ■ +31 (0)36-5346967 ■ │ - ThunderHawk │
- │ - Ash │ ■ VGA-VUL1 (sources)
- │ - The Machine │
- ■ FireHouse ■ │ - X∙N∙TRiC │ ■ CHAINDOC (textfile)
- ■ +31 (0)58-2661590 ■ │ - Utter Chaos │
- │ - Crusher │ ■ VGA-VUL2 (sources)
- │ │
- │ - Critical │ ■ BASICDOC (textfile)
- Open for more! │ - Da Frisian Force │
- │ - Tribal │ + various bbs-intros
- │ │
- ─────────────────────────┴───────────────────────┴────────────────────────────
-
- ■ (C) 1995 O∙U∙T∙L∙A∙W T∙R∙I∙A∙D ■
-
- ──────────────────────────────────────────────────────────────────────────────
-